﻿using System;
using System.Drawing.Imaging;
using System.IO;
using System.Web;

namespace Helper.FileUpload
{
    /// <summary>
    /// 썸네일 생성 도우미 클래스
    /// </summary>
    public class ThumbnailHelper : Exception
    {
        #region /// 지역 변수

        private System.Drawing.Image _SrcImage;
        private int _Width, _Height;
        private string _FileName, _FileExtName, _FileNameWithoutExtension;
        private string _ThumbName;
        private string _PhysicalPath, _VirtualPath;
        private string _URL;
        private string _SaveSubFolder;
        private string _Prefix, _Postfix;
        private int _OriginWidth, _OriginHeight;

        #endregion

        #region /// 속성 설정

        /// <summary>
        /// 이미지 가로 사이즈를 설정하거나 가져옵니다.
        /// </summary>
        public int Width
        {
            get { return _Width; }
            set { _Width = value; }
        }
        /// <summary>
        /// 이미지 세로 사이즈를 설정하거나 가져옵니다.
        /// </summary>
        public int Height
        {
            get { return _Height; }
            set { _Height = value; }
        }

        /// <summary>
        /// 이미지 URL을 가져옵니다.
        /// </summary>
        public string URL
        {
            get
            {
                string url = _URL;
                if (_SaveSubFolder != "")
                    url += _SaveSubFolder + "/";
                url += _ThumbName;
                return url;
            }
        }

        /// <summary>
        /// 서브 폴더에 저장할 경로. 없으면 기본 폴더에 저장합니다.
        /// </summary>
        public string SaveSubFolder
        {
            set
            {
                _SaveSubFolder = value.Replace("/", "");

                if (_PhysicalPath != "")
                {
                    HttpServerUtility Server = HttpContext.Current.Server;
                    _PhysicalPath = Server.MapPath(_VirtualPath + _SaveSubFolder + "/");
                }
            }
            get { return _SaveSubFolder; }
        }

        /// <summary>
        /// 파일 접두사
        /// </summary>
        public string Prefix
        {
            get { return _Prefix; }
            set { _Prefix = value; }
        }

        /// <summary>
        /// 파일 접미사
        /// </summary>
        public string Postfix
        {
            get { return _Postfix; }
            set { _Postfix = value; }
        }

        #endregion

        #region /// 생성자

        /// <summary>
        /// 기본 생성자
        /// </summary>
        public ThumbnailHelper()
        {
            _FileName = "";
            _Width = 0;
            _Height = 0;
            _Prefix = "";
            _Postfix = "thumb";
            _SaveSubFolder = "";
        }

        /// <summary>
        /// 파일명 입력 생성자
        /// </summary>
        /// <param name="fileName">파일 경로</param>
        public ThumbnailHelper(FileUploadHelper originImage)
        {
            _Width = 0;
            _Height = 0;
            _Prefix = "";
            _Postfix = "thumb";
            _SaveSubFolder = "";
            Load(originImage);
        }

        /// <summary>
        /// 사이즈 지정 생성자
        /// </summary>
        /// <param name="fileName">파일 경로</param>
        /// <param name="width">가로 사이즈</param>
        /// <param name="height">세로 사이즈</param>
        public ThumbnailHelper(FileUploadHelper originImage, int width, int height)
        {
            _Width = width;
            _Height = height;
            _Prefix = "";
            _Postfix = "thumb";
            _SaveSubFolder = "";
            Load(originImage);
        }

        #endregion

        #region /// 파일 로딩

        /// <summary>
        /// 파일 로드
        /// </summary>
        /// <param name="fileName">파일 경로</param>
        public void Load(FileUploadHelper originImage)
        {
            _FileName = originImage.PysicalPath + originImage.LastSavedFileName;
            _FileNameWithoutExtension = Path.GetFileNameWithoutExtension(_FileName);
            _FileExtName = Path.GetExtension(_FileName);
            _PhysicalPath = originImage.PysicalPath;

            _VirtualPath = originImage.FileServer.VirtualPath + originImage.VirtualSavePath;
            _URL = originImage.FileServer.Url + originImage.VirtualSavePath;
            _OriginWidth = originImage.ImageWidth;
            _OriginHeight = originImage.ImageHeight;

            if (_SaveSubFolder != "")
                SaveSubFolder = _SaveSubFolder;

        }

        #endregion

        #region /// public void Save()

        /// <summary>
        /// 썸네일 이미지 저장
        /// </summary>
        public void Save()
        {
            if (_FileName == "")
                throw new ArgumentNullException("원본 이미지가 존재하지 않습니다.");

            if (_Prefix != "")
                _ThumbName = _Prefix + "_";

            _ThumbName += _FileNameWithoutExtension;

            if (_Postfix != "")
                _ThumbName += "_" + _Postfix;

            _ThumbName += _FileExtName;

            Save(_ThumbName);
        }

        /// <summary>
        /// 썸네일 이미지 저장
        /// </summary>
        /// <param name="thumbName">저장할 파일명</param>
        public void Save(string thumbName)
        {
            int i = 0;
            string tmpExt = Path.GetExtension(thumbName);
            string tmpNameWithoutExtension = Path.GetFileNameWithoutExtension(thumbName);
            FileInfo fiFileInfo;
            string tmpName;

            //HttpContext.Current.Response.Write(_PhysicalPath);
            //HttpContext.Current.Response.End();

            // 업로드 폴더가 없으면 새로 생성.
            DirectoryInfo di = new DirectoryInfo(_PhysicalPath);
            if (!di.Exists)
                di.Create();

            // 끝에 \ 붙이기
            if (_PhysicalPath.Substring(_PhysicalPath.Length - 1) != @"\")
                _PhysicalPath += @"\";

            do
            {
                tmpName = tmpNameWithoutExtension + ((i > 0) ? "(" + ++i + ")" : "") + tmpExt;
                fiFileInfo = new FileInfo(_PhysicalPath + tmpName);
            } while (fiFileInfo.Exists);
            _ThumbName = tmpName;
            _FileExtName = tmpExt;

            if (_Width > 0 && _Height == 0)
                _Height = (int)(_OriginHeight * _Width / _OriginWidth);
            if (_Width == 0 && _Height > 0)
                _Width = (int)(_OriginWidth * _Height / _OriginHeight);

            if (_Height == 0)
                throw new ArgumentNullException("Height", "이미지 높이가 지정되지 않았습니다.");
            if (_Width == 0)
                throw new ArgumentNullException("Width", "이미지 너비가 지정되지 않았습니다.");

            _SrcImage = System.Drawing.Image.FromFile(_FileName, true);

            int thumbWidth = _Width;
            int thumbHeight = _Height;

            double ratioWidth = (double)_Width / (double)_OriginWidth;
            double ratioHeight = (double)_Height / (double)_OriginHeight;

            if (ratioWidth > ratioHeight)
                thumbWidth = (int)(ratioHeight * _OriginWidth);
            else
                thumbHeight = (int)(ratioWidth * _OriginHeight);

            using (System.Drawing.Image thumb =
                _SrcImage.GetThumbnailImage(
                    thumbWidth,
                    thumbHeight,
                    new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback),
                    IntPtr.Zero
                )
            )
            {
                switch (_FileExtName.ToLower())
                {
                    case ".jpg":
                        //throw new System.Runtime.InteropServices.ExternalException(_PhysicalPath + _ThumbName);
                        thumb.Save(_PhysicalPath + _ThumbName, ImageFormat.Jpeg);
                        break;
                    case ".gif":
                        thumb.Save(_PhysicalPath + _ThumbName, ImageFormat.Gif);
                        break;
                    case ".png":
                        thumb.Save(_PhysicalPath + _ThumbName, ImageFormat.Png);
                        break;
                }
            }
            _SrcImage.Dispose();
        }

        #endregion

        /// <summary>
        /// 썸네일 콜백 함수
        /// </summary>
        /// <returns></returns>
        public static bool ThumbnailCallback()
        {
            return false;
        }
    }
}
